﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Currency;
using UFIDA.U9.Base.Doc;
using UFIDA.U9.Base.Organization;
using UFIDA.U9.CBO.FI.BankCardType;
using UFIDA.U9.CBO.FI.ExpenseItem;
using UFIDA.U9.CBO.FI.Tax;
using UFIDA.U9.CBO.HR.Department;
using UFIDA.U9.CBO.HR.Person;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.ER.Enums;
using UFIDA.U9.ER.LoanBill;
using UFIDA.U9.ER.ReimburseBill;
using UFIDA.U9.ER.ReimburseBP;
using UFIDA.U9.ISV.ER.ImportSV;
using UFSoft.UBF.Business;

namespace ufida.u9.ait.openapi
{
    internal class ReimburseBillBase
    {
        public static ReimburseBillHead DeleteDoc(ReimburseBillHead doc)
        {
            if (doc == null) return null;

            doc = doc.Key.GetEntity();

            if (doc.DocStatus == ReimburseDocStatusEnum.Approved)
            {
                //弃审
                CancelApprovedReimburseBillBP bp=new CancelApprovedReimburseBillBP();
                bp.CurrentSysVersion = doc.SysVersion;
                bp.ReimburseBillHeadKey = doc.Key;
                bp.Do();
            }

            //删除
            using (ISession session = Session.Open())
            {
                doc.Remove();
                session.Commit();
            }
            return doc;

        }

        public static ReimburseBillHead SubmitDoc(ReimburseBillHead doc)
        {
            doc = doc.Key.GetEntity();

            if (doc.DocStatus != ReimburseDocStatusEnum.Opened)
                throw new Exception($"单号[{doc.DocNo}]状态不为开立,不能提交");

            /*
             * 这里试了各种方法,开始都是服务卡死,一直运行
             * 但是界面可以点击提交/审核没有问题
             * 最后排查出问题是因为框架方法中启用了事务,取消事务后,服务可以正常运行
             */

            //BP调用
            SubmitReimburseBillBP bp = new SubmitReimburseBillBP();
            bp.ReimburseBillHeadKey = doc.Key;
            bp.CurrentSysVersion = doc.SysVersion;
            bp.Do();
            //BE调用
            //using (Session session = Session.Open())
            //{
            //    session.InList(doc);
            //    doc.DoSubmit();
            //    session.Commit();
            //}
            //服务调用
            //SubmitReimBillSV sv = new SubmitReimBillSV();
            //sv.ReimBillDTOs = new List<ImportERBillQueryConditionDTO>()
            //{
            //    new ImportERBillQueryConditionDTO()
            //    {
            //        ID = doc.ID
            //    }
            //};
            //ReturnSumInfoDTO returnSumInfoDTO = sv.Do();

            return doc;
        }

        public static ReimburseBillHead ApproveDoc(ReimburseBillHead doc)
        {
            doc = doc.Key.GetEntity();

            if (doc.DocStatus != ReimburseDocStatusEnum.Approving)
                throw new Exception($"单号[{doc.DocNo}]状态不为提交,不能审核");

            ApprovedReimburseBillBP bp = new ApprovedReimburseBillBP();
            bp.CurrentSysVersion = doc.SysVersion;
            bp.ReimburseBillHeadKey = doc.Key;
            bp.Do();

            return doc;
        }

        public static ReimburseBillHead UnApproveDoc(ReimburseBillHead doc)
        {
            doc = doc.Key.GetEntity();

            if (doc.DocStatus != ReimburseDocStatusEnum.Approved)
                throw new Exception($"单号[{doc.DocNo}]状态不为已审,不能弃审");

            CancelApprovedReimburseBillBP bp = new CancelApprovedReimburseBillBP();
            bp.CurrentSysVersion = doc.SysVersion;
            bp.ReimburseBillHeadKey = doc.Key;
            bp.Do();

            return doc;
        }

        public static ReimburseBillHead CreateDoc(ReimburseBillAITDTOData dto)
        {
            ReimburseBillHead doc;
            using(ISession session = Session.Open())
            {
                doc = ReimburseBillHead.Create();
                CreateHead(doc, dto);
                CreateLines(doc, dto);
                CreateLoanBills(doc, dto);

                session.Commit();
            }

            //运达项目,清空缓存
            U9Utils.ClearCache();
            doc = doc.Key.GetEntity();
            return doc;
        }

        private static void CreateHead(ReimburseBillHead doc, ReimburseBillAITDTOData dto)
        {
            //doc.DocNo = dto.DocNo;
            if (string.IsNullOrEmpty(dto.ReimburseDate)) throw new Exception("ReimburseDate必填");
            doc.ReimburseDate = DateTime.Parse(dto.ReimburseDate);
            doc.BusinessDate = doc.ReimburseDate;
            if (dto.DocumentType == null) throw new Exception("DocumentType必填");
            doc.DocumentType = EntityUtils.GetEntityByCode<ReimburseDocType>(dto.DocumentType.Code);
            //组织
            doc.Org = Context.LoginOrg;
            doc.SettleOrg = doc.Org;//结算组织
            doc.LegacyOrg = doc.Org;//法人组织
            doc.ReimBurseOrg = doc.Org;//报销组织
            doc.ExpensePayOrg = doc.Org;//费用列支组织
            if (dto.ExpensePayOrg != null)
            {
                doc.ExpensePayOrg = EntityUtils.GetEntityByCode<Organization>(dto.ExpensePayOrg.Code);
            }
            doc.ExpensePayLegacyOrg = doc.Org; //列支法人组织
            doc.ExpensePayAuditOrg = doc.Org;//列支核算组织
            if (dto.ExpensePayAuditOrg != null)
            {
                doc.ExpensePayAuditOrg = EntityUtils.GetEntityByCode<Organization>(dto.ExpensePayAuditOrg.Code);
            }
            doc.AuditOrg = doc.Org;//核算组织

            //报销人
            if (dto.ReimBurseBy == null) throw new Exception("ReimBurseBy必填");
            doc.ReimBurseBy = EntityUtils.GetEntityByPath<EmployeeArchive>($"EmployeeCode='{dto.ReimBurseBy.Code}'");
            //报销人组织
            doc.ReimBurseByOrg = EntityUtils.GetEmployeeOrg(doc.ReimBurseBy);
            if (doc.ReimBurseByOrg == null) throw new Exception($"报销人[{dto.ReimBurseBy.Code}]不存在主任职业务组织");

            //实体扩展字段
            if (dto.DescFlexField != null)
            {
                doc.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, doc.DescFlexField);
            }

            //其它
            doc.BusinessType = BusinessTypeEnum.GetFromValue(2405);
            doc.SubmitOn=DateTime.Now;
            doc.SubmitBy = Context.LoginUser;
            doc.SOBAccountPeriod = EntityUtils.getPostPeriod(doc.BusinessDate);//期间
            doc.SOB = EntityUtils.getSetofBooks();
            doc.IsApplyLoan = true;//冲销借款
            doc.Currency=EntityUtils.GetEntityByCode<Currency>("C001");//币种
            doc.FC = doc.Currency;//本位币
            doc.ExpenseUse=dto.ExpenseUse;
            doc.ExpensePayProject=EntityUtils.GetEntityByCode<Project>(dto.ExpensePayProject);//项目
            doc.EmployeeBankCardType = EntityUtils.GetEntityByCode<BankCardType>(dto.EmployeeBankCardType);//银行卡类型
            doc.EmployeeBankCardNo = EntityUtils.GetEntityByCommon<EmployeeBankAccount>(dto.EmployeeBankCardNo);//银行卡号
            if (doc.EmployeeBankCardNo != null)
            {
                doc.EmployeeBankCardType = doc.EmployeeBankCardNo.CardType;
            }

            //报销部门
            doc.ReimBurseDept = EntityUtils.GetDept(doc.ReimBurseOrg.Code, dto.ReimBurseDept);
            
            //列支部门
            if (dto.ExpensePayDept == null)
            {
                doc.ExpensePayDept = doc.ReimBurseDept;//列支部门=报销部门
            }
            else
            {
                doc.ExpensePayDept = EntityUtils.GetDept(doc.ExpensePayOrg.Code, dto.ExpensePayDept);
            }
            //列支人员
            if (dto.ExpensePayBy == null)
            {
                doc.ExpensePayBy = doc.ReimBurseBy;//列支人员=报销人员
            }
            else
            {
                doc.ExpensePayBy=EntityUtils.GetEntityByPath<EmployeeArchive>($"EmployeeCode='{dto.ExpensePayBy.Code}'");
            }

        }

        private static void CreateLines(ReimburseBillHead doc, ReimburseBillAITDTOData dto)
        {
            int rowno = 0;
            foreach(var linedto in dto.ReimburseBillDetails)
            {
                
                ReimburseBillDetails line = ReimburseBillDetails.Create(doc);
                rowno += 10;
                if (linedto.LineNum == 0)
                {
                    line.LineNum = rowno;
                }
                else
                {
                    line.LineNum = linedto.LineNum;
                }

                //金额/税额

                //不传税组合,通过 税额 计算
                //if (linedto.TaxSchedule == null) throw new Exception("TaxSchedule必填");
                //line.TaxSchedule=EntityUtils.GetEntityByCode<TaxSchedule>(linedto.TaxSchedule.Code);
                //line.Tax = line.TaxSchedule.TaxScheduleTaxs[0].Tax;
                //line.TaxRate = EntityUtils.GetTaxRate(line.TaxSchedule);

                line.ReimburseMoney = linedto.ReimburseMoney;//报销金额 含税
                line.ReimburseMoneyFC = linedto.ReimburseMoney;
                //发票金额
                if (linedto.InvoiceMoney == 0)
                {
                    line.InvoiceMoney = line.ReimburseMoney;
                }
                else
                {
                    line.InvoiceMoney = linedto.InvoiceMoney;
                }
                line.InvoiceMoneyFC = line.InvoiceMoney;

                //不含税金额
                if (linedto.NonTaxMoney == 0)
                {
                    //不含税金额=含税金额/(1+税率)
                    line.NonTaxMoney = line.ReimburseMoney / (1 + line.TaxRate);
                    line.NonTaxMoney=U9Utils.GetRoundMoney(doc.Currency, line.NonTaxMoney);//精度
                }
                else
                {
                    line.NonTaxMoney = linedto.NonTaxMoney;
                }
                line.NonTaxFCMoney = line.NonTaxMoney;
                
                //税额=含税-不含税
                line.TotalTax = line.ReimburseMoney - line.NonTaxMoney;
                line.FCTotalTax=line.TotalTax;

                //税率
                line.TaxRate = line.TotalTax / line.NonTaxMoney;

                //实体扩展字段
                if (linedto.DescFlexField != null)
                {
                    line.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                    DTOUtils.DTOPropCopy(linedto.DescFlexField, line.DescFlexField);
                }

                //其它
                line.ExpenseItem = EntityUtils.GetEntityByCode<ExpenseItem>(linedto.ExpenseItem);//收支项目
                line.TCNum = linedto.TCNum;
                line.ReimbursePercent = 1;//报销比例
                line.ReimburseCurrency = doc.Currency;
                line.Rate = 1;//汇率
                line.FromDate = doc.BusinessDate;
                if (!string.IsNullOrEmpty(linedto.FromDate))
                {
                    line.FromDate = DateTime.Parse(linedto.FromDate);
                }
                if (!string.IsNullOrEmpty(linedto.ToDate))
                {
                    line.ToDate=DateTime.Parse(linedto.ToDate);
                }
                line.ToPlace = linedto.ToPlace;
                line.SubsidyDays = linedto.SubsidyDays;
                line.ExpensePayProject = doc.ExpensePayProject;//项目
                if (linedto.ExpensePayProject != null)
                {
                    line.ExpensePayProject = EntityUtils.GetEntityByCode<Project>(linedto.ExpensePayProject);
                }
                line.ExpensePayDept = doc.ExpensePayDept;//列支部门
                if (linedto.ExpensePayDept != null)
                {
                    line.ExpensePayDept= EntityUtils.GetDept(doc.ExpensePayOrg.Code, linedto.ExpensePayDept);
                }
                line.ExpensePayBy = doc.ExpensePayBy;//列支人员
                if (linedto.ExpensePayBy != null)
                {
                    line.ExpensePayBy= EntityUtils.GetEntityByPath<EmployeeArchive>($"EmployeeCode='{linedto.ExpensePayBy.Code}'");
                }

            }
        }

        private static void CreateLoanBills(ReimburseBillHead doc, ReimburseBillAITDTOData dto)
        {
            if (dto.LoanBills == null || dto.LoanBills.Count == 0)
            {
                doc.IsApplyLoan = false;
                return;
            }
            foreach (var linedto in dto.LoanBills)
            {
                ReimburseApplyLoanBill line = ReimburseApplyLoanBill.Create(doc);

                //借款单
                if (linedto.LoanBill == null) throw new Exception("LoanBill必填");
                line.LoanBill = EntityUtils.GetDocEntity<LoanBill>(linedto.LoanBill.Code);
                if (line.LoanBill == null) throw new Exception($"查找借款单失败,单号:[{linedto.LoanBill.Code}]");

                //金额
                line.ApplyMoney=linedto.ApplyMoney;//冲销金额
                line.ApplyMoneyFC = linedto.ApplyMoney;//冲销本币金额
                line.LoanBalanceMoney = line.LoanBill.LoanBalance;//借款余额
                line.LoanBalanceMoneyFC = line.LoanBill.LoanFuntionalBalance;//借款本币余额
                line.AppliedLoanBalanceMoney = line.LoanBalanceMoney - line.ApplyMoney;//冲销后借款余额
                line.AppliedLoanBalanceMoneyFC = line.AppliedLoanBalanceMoney;//冲销后借款本币余额

                //其它
                line.LoanCurrency = line.LoanBill.LoanCurrency;//币种
                line.LoanBillDocType = line.LoanBill.LoanBillType;//借款单据类型

            }
        }
    }
}
